package ao.util.compress;

import net.contrapunctus.lzma.LzmaInputStream;
import net.contrapunctus.lzma.LzmaOutputStream;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Uses 7zip compression.
 */
public class Compressor
{
    //-------------------------------------------------------------------------
    private Compressor() {}

    
    //-------------------------------------------------------------------------
    public static byte[] deflate(byte data[])
    {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        LzmaOutputStream      lzma = new LzmaOutputStream( baos );

        try
        {
            lzma.write( data );
            lzma.close();
            return baos.toByteArray();
        }
        catch (IOException e)
        {
            throw new Error( e );
        }
    }

    public static byte[] deflate(String data)
    {
        return deflate(data.getBytes());
    }

    
    //-------------------------------------------------------------------------
    public static byte[] inflate(byte compressedData[])
    {
        ByteArrayInputStream bais =
                new ByteArrayInputStream( compressedData );
        LzmaInputStream      lzma = new LzmaInputStream( bais );

        try
        {
            byte         buffer[]     = new byte[ 1024 * 32 ];
            List<byte[]> bufferBuffer = new ArrayList<byte[]>();

            int size;
            while ((size = lzma.read(buffer)) != -1)
            {
                bufferBuffer.add(
                        Arrays.copyOf(buffer, size));
            }

            if (bufferBuffer.size() == 0)
            {
                return new byte[0];
            }
            else if (bufferBuffer.size() == 1)
            {
                return bufferBuffer.get(0);
            }
            else
            {
                int lastLength = bufferBuffer.get(
                                bufferBuffer.size() - 1 ).length;
                int totalSize =
                        (bufferBuffer.size() - 1) * buffer.length +
                        lastLength;
                byte inflated[] = new byte[ totalSize ];
                for (int i = 0; i < bufferBuffer.size(); i++)
                {
                    System.arraycopy(
                            bufferBuffer.get(i),
                            0,
                            inflated,
                            i * buffer.length,
                            bufferBuffer.get(i).length);
                }
                return inflated;
            }
        }
        catch (IOException e)
        {
            throw new Error( e );
        }
    }

    public static String inflateStr(byte compressedData[])
    {
        return new String(inflate(compressedData));
    }
}
